﻿//-----------------------------------------------------------------------
// <copyright file="TileData.cs" company="Steve Syrell">
//     Copyright 2012 Steve Syrell
// </copyright>
//-----------------------------------------------------------------------

namespace SteveSyrell.Tools.Phone.LiveTiles
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.IO.IsolatedStorage;
    using System.Runtime.Serialization;
    using System.Windows;
    using System.Windows.Media.Imaging;
    using Shell = Microsoft.Phone.Shell;

    /// <summary>
    /// The base class for tile data.
    /// </summary>
    [KnownType(typeof(FlipTileData))]
    [KnownType(typeof(CycleTileData))]
    [DataContract]
    public abstract class TileData
    {
        /// <summary>
        /// The size of the small tile in pixels.
        /// </summary>
        public static readonly Size SmallTileSize = new Size(159, 159);

        /// <summary>
        /// The size of the medium tile in pixels.
        /// </summary>
        public static readonly Size MediumTileSize = new Size(336, 336);

        /// <summary>
        /// The size of the large tile in pixels.
        /// </summary>
        public static readonly Size WideTileSize = new Size(691, 336);

        /// <summary>
        /// The prefix used in image uris.
        /// </summary>
        private const string TileImageUriPrefix = "isostore:/";

        /// <summary>
        /// Initializes a new instance of the TileData class.
        /// </summary>
        protected TileData()
        {
            this.SupportsWideTile = false;
        }

        /// <summary>
        /// Gets or sets the navigation uri for this tile.
        /// </summary>
        [DataMember]
        public Uri NavigationUri { get; set; }

        /// <summary>
        /// Gets or sets the count to display on the front of the tile.
        /// </summary>
        [DataMember]
        public int Count { get; set; }

        /// <summary>
        /// Gets or sets the title to display on the front of the tile.
        /// </summary>
        [DataMember]
        public string Title { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether or not this tile supports the wide tile mode.
        /// </summary>
        [IgnoreDataMember]
        protected internal bool SupportsWideTile { get; protected set; }

        /// <summary>
        /// Gets the system shell tile data that is used to actually create the tile in the system.
        /// </summary>
        /// <param name="verifyUiElements">A value indicating whether to verify UI elements.</param>
        /// <returns>The system shell tile data.</returns>
        internal abstract Shell.ShellTileData GetSystemShellTileData(bool verifyUiElements);

        /// <summary>
        /// Cleans up any resources used by this tile.
        /// </summary>
        internal abstract void CleanupResources();

        /// <summary>
        /// Copies non-updated old tile data to this tile data instance.
        /// This is used when updating tile data if only new (updated) data is applied.
        /// </summary>
        /// <param name="oldTileData">The old tile data instance.</param>
        internal abstract void CopyNonUpdatedData(TileData oldTileData);

        /// <summary>
        /// Gets a list of the file names of the images in use for this tile.
        /// </summary>
        /// <returns>A list of the file names of the images in use for this tile.</returns>
        internal abstract List<string> GetImageFileNames();

        /// <summary>
        /// Creates and saves the image to use on the tile.
        /// </summary>
        /// <param name="uiElement">The UI element to use to create the image.</param>
        /// <param name="tileSize">The size of the tile.</param>
        /// <returns>The uri of the image file.</returns>
        protected Uri CreateAndSaveTileImage(UIElement uiElement, Size tileSize)
        {
            // Create the name of the image file to create.
            string fileName = System.IO.Path.Combine(LiveTileHelper.TileImageLocation, Guid.NewGuid().ToString() + ".jpg");

            // Render the element to an image.
            uiElement.UpdateLayout();
            uiElement.Measure(tileSize);
            uiElement.Arrange(new Rect(new Point(0, 0), tileSize));
            WriteableBitmap wb = new WriteableBitmap((int)tileSize.Width, (int)tileSize.Height);
            wb.Render(uiElement, null);
            wb.Invalidate();

            // Now save the image to disk.
            try
            {
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (var stream = store.OpenFile(fileName, FileMode.OpenOrCreate))
                    {
                        wb.SaveJpeg(stream, wb.PixelWidth, wb.PixelHeight, 0, 100);
                    }
                }
            }
            catch (IsolatedStorageException)
            {
                return null;
            }

            return new Uri(TileData.TileImageUriPrefix + fileName, UriKind.Absolute);
        }

        /// <summary>
        /// Deletes the specified tile image.
        /// </summary>
        /// <param name="uriOfImageToDelete">The URI of the image to delete.</param>
        protected void DeleteTileImage(Uri uriOfImageToDelete)
        {
            try
            {
                using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    if (store.FileExists(uriOfImageToDelete.LocalPath))
                    {
                        store.DeleteFile(uriOfImageToDelete.LocalPath);
                    }
                }
            }
            catch (IsolatedStorageException)
            {
                // do nothing.
            }
        }

        /// <summary>
        /// Creates and saves all specified tile images for this tile.
        /// </summary>
        protected abstract void CreateAndSaveTileImages();
    }
}
